Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement codemod for replacing unsafe xml methods with defusedxml #76

Merged
merged 2 commits into from
Oct 17, 2023

Conversation

drdavella
Copy link
Member

@drdavella drdavella commented Oct 16, 2023

Overview

Implement codemod for replacing unsafe xml methods with defusedxml

Description

  • The Python documentation explicitly calls out the provided xml modules as unsafe and recommends the use of defusedxml, which is a third-party package
  • This codemod replaces the unsafe methods from xml with safe ones from defusedxml
  • In an effort to break this up into smaller units, this PR only contains the transformation logic itself
  • I was able to reuse quite a bit of code from the https-connection codemod
  • NOTE: This codemod is not enabled in the registry yet. See below for additional work.

Next Steps

  • Add the defusedxml dependency. I am leaving this as separate work because I want to make sure we are adding a good CodeTF comment as well, which requires some additional infrastructure.
  • Implement an integration test, add documentation, add codemod to the registry

@codecov
Copy link

codecov bot commented Oct 17, 2023

Codecov Report

Merging #76 (08735a5) into main (21ae8b2) will increase coverage by 0.12%.
The diff coverage is 96.61%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #76      +/-   ##
==========================================
+ Coverage   96.21%   96.33%   +0.12%     
==========================================
  Files          46       48       +2     
  Lines        1824     1885      +61     
==========================================
+ Hits         1755     1816      +61     
  Misses         69       69              
Files Coverage Δ
src/codemodder/cli.py 100.00% <100.00%> (ø)
src/core_codemods/use_defused_xml.py 100.00% <100.00%> (ø)
src/core_codemods/https_connection.py 97.36% <96.87%> (+3.82%) ⬆️
src/codemodder/codemods/imported_call_modifier.py 93.61% <93.61%> (ø)

@drdavella drdavella marked this pull request as ready for review October 17, 2023 01:21
src/core_codemods/https_connection.py Outdated Show resolved Hide resolved
src/core_codemods/use_defused_xml.py Outdated Show resolved Hide resolved
src/core_codemods/use_defused_xml.py Outdated Show resolved Hide resolved
src/core_codemods/use_defused_xml.py Outdated Show resolved Hide resolved
src/core_codemods/use_defused_xml.py Show resolved Hide resolved
src/core_codemods/use_defused_xml.py Outdated Show resolved Hide resolved
"""

new_code = f"""
from xml.etree.{module} import ElementPath
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line is unused so I would've expected the remove import visitor to have removed it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an interesting point...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this be something you can resolve now or ticket for later?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll ticket it for later; I don't think it directly is a result of this PR.

Copy link
Contributor

@andrecsilva andrecsilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only caveat is the comment about the _matching_function_names. Treat the others as suggestions.

Comment on lines +66 to +88
# it is a simple name, e.g. call() -> module.new_call()
return self.update_simple_name(
true_name, original_node, updated_node, new_args
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small clarification om this bit of code here.
Within the context of https codemod this comment and logic was accurate. But this may not be general enough.
Consider:

from lib import call
call()

We have the option to simply change the call...

from lib import call
import lib2
lib2.call2()

or changing the call and import:

from lib2 import call2
call2()

The second has an advantage of not having a possibly useless import (not much of a problem since we have a codemod to amend that). Then again, then reason why I've favored the first one for the https codemod was because the change became more explicit.

The second transformation is a bit harder to do but within the realm of possibility. Just tell me if you want me to support that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrecsilva that makes sense. It might be good to revisit at some point but right now I like that the updated call becomes completely explicit.

src/core_codemods/https_connection.py Outdated Show resolved Hide resolved
src/codemodder/codemods/imported_call_modifier.py Outdated Show resolved Hide resolved
src/codemodder/codemods/imported_call_modifier.py Outdated Show resolved Hide resolved

METADATA_DEPENDENCIES = (PositionProvider,)

matching_functions = {
matching_functions: set[str] = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could have this be a keys-only dict. It would feel more consistent.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not aware of any such construct; do you just mean a dict where the values are None?

@drdavella
Copy link
Member Author

Codecov is upset but I don't think I actually changed the coverage here; I just refactored some previously uncovered lines into a new file that it doesn't recognize.

@@ -43,7 +43,7 @@ class CsvListAction(argparse.Action):
argparse Action to convert "a,b,c" into ["a", "b", "c"]
"""

def __call__(self, parser, namespace, values: str, option_string=None):
def __call__(self, parser, namespace, values, option_string=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was mypy, right? Isn't it weird that we fix a typing problem by ... removing typing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I (wrongly) introduced this on a previous PR when mypy wasn't working for me. The underlying code itself is not typed correctly and I thought adding this would fix it (but it does not).

@drdavella drdavella requested a review from clavedeluna October 17, 2023 19:26
@drdavella drdavella merged commit 57df277 into main Oct 17, 2023
10 of 11 checks passed
@drdavella drdavella deleted the use-defused-xml branch October 17, 2023 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants